﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using DotNetX;
using BugzX.Repositories;
using System.Collections.Specialized;
using BugzX;

namespace BugzX.Services
{
    /// <summary>
    /// Summary description for Projects
    /// </summary>
    public class Bugs : IHttpHandler
    {
        public BugzXDBEntities DBContext
        {
            get { return _dbContext; }
            set { _dbContext = value; }
        }
        private BugzXDBEntities _dbContext = new BugzXDBEntities();

        public void ProcessRequest(HttpContext context)
        {
            string action = context.Request.Params["action"].Trim().ToLower();

            object response = null;

            if (action == "getbug")
            {
                response = this.GetBug(context);
            }
            else if (action == "getbugtypes")
            {
                response = this.GetBugTypes(context);
            }
            else if (action == "getbugstatuses")
            {
                response = this.GetBugStatuses(context);
            }
            else if (action == "updatebug")
            {
                response = this.UpdateBug(context);
            }

            context.Response.ContentType = "application/json";
            context.Response.Write(new JavaScriptSerializer().Serialize(response));

            context.Response.Flush();
            context.Response.End();
        }

        private object GetBug(HttpContext context)
        {
            int bugId = context.Request.Params["bugId"].ToInt32OrZero();

            return from b in this.DBContext.Bugs.AsEnumerable()
                   where b.BugId == bugId
                   select new
                   {
                       bugId = b.BugId,
                       title = b.Title,
                       type = b.Type,
                       ownerId = b.OwnerId,
                       ownerName = UserRepository.GetUserName(b.OwnerId),
                       description = b.BugNotes.AsEnumerable().First().Notes,
                       component = b.ProjectComponent.Name,
                       priority = b.Priority,
                       stamp = b.Stamp.ToShortDateString(),
                       parentTo = from p in b.BugDependenciesParent select p.BugId,
                       dependsOn = from p in b.BugDependencies select p.ParentId,
                       status = b.Status,
                   };
        }

        private object GetBugTypes(HttpContext context)
        {
            return EnumExtensions.ToStringDictionary(typeof(BugType));
        }

        private object GetBugStatuses(HttpContext context)
        {
            return EnumExtensions.ToStringDictionary(typeof(BugStatus));
        }

        private object UpdateBug(HttpContext context)
        {
            int bugId = context.Request.Params["bugId"].ToInt32OrZero();
            string description = context.Server.UrlDecode(context.Request.Params["description"].ToString());
            BugType type = (BugType)context.Request.Params["type"].ToInt32OrZero();
            BugStatus status = (BugStatus)context.Request.Params["status"].ToInt32OrZero();
            string parentTo = context.Server.UrlDecode(context.Request.Params["parentTo"].ToString());
            string dependsOn = context.Server.UrlDecode(context.Request.Params["dependsOn"].ToString());

            var dbContext = new BugzXDBEntities();

            var bug = (from b in dbContext.Bugs
                       where b.BugId == bugId
                       select b).SingleOrDefault();

            bool result = false;
            string error = String.Empty;

            if (bug != null)
            {
                FormChecker checker = new FormChecker();

                var notes = bug.BugNotes.First();
                notes.Notes = checker.GetString(description, "Description");

                bug.Type = (int)type;
                bug.Status = (int)status;

                if (!this.UpdateBugParentTo(bug, parentTo, dbContext))
                {
                    checker.AddError("Please enter valid Parent To ids");
                }

                if (!this.UpdateBugDependentOn(bug, dependsOn, dbContext))
                {
                    checker.AddError("Please enter valid Dependent On ids");
                }

                if (checker.HasErrors)
                {
                    error = checker.ErrorsByBRTag;
                }
                else
                {
                    result = true;

                    dbContext.SaveChanges();
                }
            }

            return new
            {
                result = result,
                error = error,
            };
        }

        private bool UpdateBugParentTo(Bug bug, string parentTo, BugzXDBEntities entities)
        {
            string[] ids = parentTo.Split(',');

            var parents = from deps in entities.BugDependencies
                          where deps.ParentId == bug.BugId
                          select deps;

            foreach (var p in parents)
            {
                entities.BugDependencies.DeleteObject(p);
            }

            foreach (string id in ids)
            {
                if (!id.IsInt32())
                    continue;

                int idAsInt = Convert.ToInt32(id);

                var b = (from bu in entities.Bugs
                         where bu.BugId == idAsInt
                         select bu).SingleOrDefault();

                if (b == null)
                    return false;

                BugDependency dep = new BugDependency();
                dep.BugId = b.BugId;
                dep.ParentId = bug.BugId;

                entities.BugDependencies.AddObject(dep);
            }

            return true;
        }

        private bool UpdateBugDependentOn(Bug bug, string dependentOn, BugzXDBEntities entities)
        {
            string[] ids = dependentOn.Split(',');

            var dependents = from deps in entities.BugDependencies
                             where deps.BugId == bug.BugId
                             select deps;

            foreach (var p in dependents)
            {
                entities.BugDependencies.DeleteObject(p);
            }

            foreach (string id in ids)
            {
                if (!id.IsInt32())
                    continue;

                int idAsInt = Convert.ToInt32(id);

                var b = (from bu in entities.Bugs
                         where bu.BugId == idAsInt
                         select bu).SingleOrDefault();

                if (b == null)
                    return false;

                BugDependency dep = new BugDependency();
                dep.BugId = bug.BugId;
                dep.ParentId = b.BugId;

                entities.BugDependencies.AddObject(dep);
            }

            return true;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}